/*

* client_session.cpp
 *
 *  Created on: Aug 1, 2013
 *      Author: killerg
 */

#include "logon_deps.h"

#include "client_session.h"
#include "server_mgr.h"
#include "logon.h"
#include "logon_cfg.h"
#include "auth_session.h"

#include "share/clock.h"
#include "share/patterns.h"
#include "share/net_s.h"
#include "share/msg.h"
#include "share/util.h"
#include "share/cl_msg.pb.h"
#include "share/sl_msg.pb.h"
#include "share/profiler.h"
#include "share/msg_coder.h"

bool client_session_t::send_msg(cl::LMsg* &msg) {
    return g_logon.clisess_mgr->send_msg(this, msg);
}

void client_session_t::on_connect() {
    stage = ELConnected;
}

void client_session_t::on_disconnect() {
    stage = ELInvalid;
}

void client_session_t::update() {
    ++g_logon.count[stage];
}

void handle_default(client_session_t* sess, cl::CMsg* msg) {
    UTIL_LOG(W, "error msg %d has not handler\n", msg->id());
    sess->_trans->disconnect();
}

void handle_cauth(client_session_t* sess, cl::CMsg* msg) {
    if (sess->stage != ELConnected && sess->stage != ELAuthing) {
        sess->_trans->disconnect();
        return;
    }

    if (g_logon.authsess->authing > 200) {
        CREATE_CL_LMSG(LAuth, auth);
        auth->set_quing(g_logon.authsess->authing);
        sess->send_msg(___msg);

    	return;
    }

    sess->stage = ELAuthing;
    sess->mc = msg->auth().mc();

    if (!g_logon.authsess->tran.is_connected()) {
        sess->_trans->disconnect();
        return;
    }

    if (!g_logon.authsess->base::tran.is_connected()) {
        sess->_trans->disconnect();
        return;
    }

    Json::Value djson = to_json(msg->auth().data());
    if (!djson.isObject()) {
        sess->_trans->disconnect();
        return;
    }

    g_logon.authsess->post_auth(sess->_sessid,
    							msg->auth().data(),
    							msg->auth().mc());
}

void handle_cserverlist(client_session_t* sess, cl::CMsg* msg) {
    if (sess->stage != ELAuthed && sess->stage != ELSelecting) {
        sess->_trans->disconnect();
        return;
    }
    sess->stage = ELSelecting;

    CREATE_CL_LMSG(LServerList, serverlist);
    int size = g_logon.svrmgr->info.size();
    for (int i=1; i<size; ++i) {
    	const auto &info = g_logon.svrmgr->info[i];
    	if (info.serverid > g_logon.svrmgr->maxid)
    		break;

        auto info2 = serverlist->add_info();
    	info2->set_serverid(info.serverid);
    	info2->set_status(info.status);
    }
    sess->send_msg(___msg);
}

void handle_cselect(client_session_t* sess, cl::CMsg* msg) {
    if (sess->stage != ELSelecting) {
        sess->_trans->disconnect();
        return;
    }
    auto cselect = msg->select();
    int32_t serverid = cselect.serverid();

    if (!g_logon.svrmgr->is_valid_serverid(serverid)) {
        sess->_trans->disconnect();
        return;
    }
    int64_t playerid = sess->playerid + int64_t(serverid) * co::MaxAccountNum;
    server_info_t &info = g_logon.svrmgr->info[serverid];
    std::string ip;
    int32_t port = -1;
    int32_t key = -1;
    cl::ELSelectErr error;

    if (info.status == co::ESS_Running && info.sess) {
        error = cl::ELSE_Ok;
        ip = info.ip;
        port = info.port;
        key = 111;

        sess->key = key;

        CREATE_SL_LMSG(LPlayerWillLogon, playerwilllogon);
        playerwilllogon->set_sessid(sess->_sessid);
        playerwilllogon->set_account(sess->account);
        playerwilllogon->set_channel(sess->plat);
        playerwilllogon->set_key(key);
        playerwilllogon->set_playerid(playerid);
        playerwilllogon->set_mc(sess->mc);
        playerwilllogon->set_active(sess->active_time);
        info.sess->send_msg(___msg);
    } else {
        error = cl::ELSE_ServerOffline;
        CREATE_CL_LMSG(LSelect, select);
        select->set_key(key);
        select->set_ip(ip);
        select->set_port(port);
        select->set_playerid(playerid);
        select->set_error(error);
        sess->send_msg(___msg);
    }
}

bool clientsess_mgr_t::init() {
    bool ok = base::init(
            g_cfg->ListenClientIp.c_str(),
            g_cfg->ListenClientPort,
            10000,
            10,
            20.0f,
            2048,
            true,
            200
            );

    if (g_cfg->DecodeClient) {
        base::net.code_cb = encmsg;
    }

    if (!ok) {
        UTIL_LOG(E, "clientsess_mgr_t::init listen for client err at %s:%d",
                g_cfg->ListenClientIp.c_str(),
                g_cfg->ListenClientPort);
        return false;
    }
    UTIL_LOG(I, "listenint for client at %s:%d",
            g_cfg->ListenClientIp.c_str(),
            g_cfg->ListenClientPort);

    ok = ok && base::reg(cl::ID_CAuth       , handle_cauth      );
    ok = ok && base::reg(cl::ID_CServerList , handle_cserverlist);
    ok = ok && base::reg(cl::ID_CSelect     , handle_cselect     );

    return ok;
}
const char* LogonStageName[] = {
        "Inv",
        "Cnd",
        "Aug",
        "Aud",
        "Slg",
        "Sld"
};

